home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-01-05 | 26.3 KB | 1,132 lines |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 3D Library
-
- version 1.0
-
-
-
- by Steven Ludtke
-
-
-
- January 5, 1990
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- NOTICE
-
-
-
- The 3d library and all associated software in this distribution
-
- is Copyright 1990 by Steven J. Ludtke. You have permission to
-
- use and/or modify this code for any purpose commercial or non-
-
- commercial with two conditions : I must be given credit in any
-
- distributed product's documentation, and if any part of this
-
- package is used in any commercial product (even Shareware) one
-
- free copy of said software must be sent to me at the following
-
- address : Steven Ludtke, 406 Yale Cir., Glenwood Springs, CO
-
- 81601; all other royalties are waived. This Copyright notice
-
- must accompany any distributions of any part of this package,
-
- and in general, the package should be distributed intact, with
-
- no modifications. This notice must not be removed from the 3d.c,
-
- test.c, and cube.c source code in this release.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 2 - January 5, 1990
-
-
-
-
-
-
-
-
-
-
- Introduction
-
- ---------------------
-
-
-
- This library represents an attempt to provide the Amiga
-
- community with a high speed, easy to use 3d display library for
-
- C programmers. The library uses the transformation matrix
-
- method, which is the fastest method I know to do 3d
-
- transformations while still providing relatively intuitive
-
- rotations. Integer arithmetic is used for speed. Additionally,
-
- the data is stored in a format that will make it easy to
-
- optimize the code in assembly language. I wrote the code for
-
- Aztec C, but I haven't converted anything to assembly language
-
- yet, so the current version should work with Lattice as well. I
-
- haven't tested it, but I don't believe I did anything that is
-
- compiler dependent.
-
- The library provides what I consider relatively high speed 3d
-
- displays. It can rotate and draw roughly 500 lines/second. Once
-
- I've converted the rotation code to optimized assembly, I expect
-
- the time required for the calculation portion of the display to
-
- be reduced by at least a factor of 4. With the Amiga's graphics
-
- coprocessor, filled polygons can be drawn almost (perhaps 70-
-
- 80%) as fast as the lines.
-
- Since a number of the parameters used in the library are
-
- application specific, the 'library' is actually a C source file
-
- that you include in your program. This is done primarily for
-
- speed. If some of the parameters were variables rather than
-
- #defines, the library would run significantly slower. The code
-
- is relatively small, and it seems unlikely that more than one 3d
- Page 3 - January 5, 1990
- application would be active at one time, so C source seems to me
-
- to be a reasonable way to go. If anyone has a better idea for
-
- future versions, I'd love to hear it.
-
-
-
- Included in this package are the following :
-
- 3d.c - The actual library code. This file is included in any
-
- program you use the 3d routines in. It must appear in
-
- the correct place in your program. Read the instr. or
-
- look at one of the sample programs for more info.
-
- 3d.doc - This file.
-
- makefile - An Aztec makefile for the two sample programs.
-
- cube.c - A sample program that does double buffered animation
-
- of a cube moving around. There is a reason it doesn't
-
- move very smoothly. Look at the code before you think
-
- that's the best the library can do.
-
- test.c - A sample program that allows you to display 3d files
-
- that are in a standard (non-IFF) format. Several
-
- sample files are included. Look at the source for
-
- instructions.
-
- cube.3d - A cube for use with test.c
-
- earth.3d - Outline of the earth's continents for use with
-
-
-
-
-
- test.c. It should work pretty well with d3surf().
-
- rocket.3d- This is an example of a file that won't work
-
- correctly with 3dsurf().
-
- lay.3d - 4 squares to try with test.c
-
-
-
- The two sample programs were written for Aztec C ver 3.6. As
-
- far as I know it will work as is with Lattice, but I could be
-
- wrong. I didn't supply executable for the samples to save a
-
- little space in the distribution.
-
- I have tested all the routines fairly well myself, but this
-
- release is the first time anyone else has had the chance to use
-
- any of this stuff. I should probably call this version a beta-
-
- test release, but I won't. If you have any problems or
-
- suggestions I strongly encourage you to send me a message.
-
- Besides, knowing that someone actually is using this package
-
- would give my ego a little boost.
-
-
-
- I can be contacted via any of the following :
-
- stevel@tybalt.caltech.edu (until June 90)
-
- stevel@citiago.bitnet (until June 90)
-
- gluon@theta.caltech.edu
-
- 72335,1537 (compuserve)
-
- Steve Ludtke, 1-54 Caltech, Pasadena CA 91126 (until June 90)
-
- Steve Ludtke, 406 Yale Cir, Glen. Spgs. CO 81601 (after that)
-
-
-
- My current plans for the next version are as follows :
-
- 1. Convert much of the code to assembly for speed.
-
- 2. Perhaps add alternative methods for specifying angles, etc...
- Page 4 - January 5, 1990
- I've heard of some scheme using quaternation (sp?) that's
-
- supposed to be easier for many applications.
-
- 3. Perhaps I'll try to add some primitive shading routines
-
- (simple lighting effects).
-
- 4. Anything you suggest ...
-
-
-
- Please talk to me. I like to get mail. Btw, this code should
-
- be pretty easy to convert for use on other machines. All you
-
- really need to change is the actual graphics function calls.
-
-
-
-
-
- Here's the actual programming info. Info on structures follows
-
- the function information. I tried to make it as easy to use as
-
- possible.
-
-
-
- Before your try to write your own code, you should probably
-
- look at one of the examples. I'll summarize the basic steps
-
- here.
-
- Before you include the 3d.c file, you need to have several
-
- #define statements in you program. If necessary you can replace
-
- some of the defines with global variables, but you should avoid
-
- this as it will slow the program down. The defines you need are
-
- as follows :
-
-
-
- #define D3VDIST 5000 <- This is the distance from the
-
- observer to the vanishing point. It
-
- is only used with rotatev().
-
- #define REZ 1024 <- Since the program uses integer
-
- math, it must use several bits
-
- for fractional calculations. 1024
-
- would give 3 digits of accuracy. This
-
- number needs to be a power of 2 for
-
- upward compatibility. In general it
-
- should be at least as large as the
-
- # of pixels in the display you use.
-
- The larger it is, the smaller your
-
- space for points is. REZ=1024 leaves
-
- you with ~4,000,000 possible values
-
- for 'x','y','z'.
- Page 5 - January 5, 1990
- #define REZB 10 <- This is the number of bits in REZ. It
-
- isn't currently used. It will be in
-
- the next version, so update it.
-
- #define XCEN 250 <- This is the x coord (in the bitmap)
-
- of the center (x=0) coordinate for 3d
-
- displays.
-
- #define YCEN 100 <- Same for y coord.
-
- #define XHI 600 <- This is the highest x value in your
-
- bitmap. Anything above this will be
-
- clipped by the drawing routines.
-
- #define YHI 180 <- Same for y.
-
- #define XLO 0 <- Low x clipping value.
-
- #define YLO 0 <- Low y clipping value.
-
- #define ASPECT 22/10 <- This is the aspect ratio used to
-
- insurea square coord system on the
-
- screen. 22/10 is correct for 640X200
-
- mode. Obviously 11/10 should be used
-
- in 320X200 mode.
-
- #include "3d.c"
-
-
-
-
-
- Next, you should initialize a VECTOR structure with enough
-
- free memory for your vertex data. Don't forget to allocate
-
- memory for 'tx','ty', and 'tz', too. Allocate memory for a LINES
-
- array as well. Now you can fill in the data in the VECTOR and
-
- LINES structures. Information on this data appears near the end
-
- of the documentation.
-
- Now set up a window or screen (something with a valid
-
- RastPort) or two for double buffering. If you intend to use
-
- d3surf(), call Init3Ras() with one or both RastPorts.
-
- Now SetDrMd() for all RastPorts. If you don't have color data
-
- in your LINES structure, also do a SetAPen() and a SetOPen()
-
- (for surfaces) for all RastPorts.
-
- Now you can actually display data. setxfm() allows you to set
-
- the viewpoint for the drawing. rotatev() or rotate() is used to
-
- actually perform the rotations with or without perspective.
-
- d3surf() and d3lines() can then be used to render the data in a
-
- RastPort.
-
- When you're all done, don't forget to call Exit3d() if you
-
- called Init3Ras(). DON'T call it if you only used d3lines().
-
- Simple huh ??? : )
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Page 6 - January 5, 1990
-
-
-
-
-
-
-
-
-
-
-
-
- FUNCTION DEFINITIONS :
-
-
-
- setxfm - Set rotation and translation values for next xform.
-
-
-
- USAGE :
-
- setxfm(a1,a1,a3,x,y,z,m,d)
-
- double a1,a2,a3;
-
- long x,y,z,m,d;
-
-
-
- FUNCTION :
-
- This routine sets transformation matrix values based on the
-
- parameters you pass it. The actual matrix is a global array,
-
- however for upward compatibility's sake, you shouldn't access it
-
- except through this routine.
-
-
-
- INPUTS :
-
- The three parameters, 'a1-a3' are rotation angles in radians
-
- (see the description of rotations following the structure
-
- definitions). 'x','y','z' are translation parameters. Since
-
- positional values are integral, the translation values must also
-
- be integral.
-
- 'n' and 'd' are scaling factors. Since integer arithmetic is
-
- used, a fraction is used for the scaling factor. 'n' is the
-
- numerator and 'd' is the denominator of the scaling factor. The
-
- way this is implemented, it doesn't slow the translations down,
-
- so if you don't need it just set 'n' and 'd' to 1. It will be
-
- just like they didn't exist.
- Page 7 - January 5, 1990
-
-
- OUTPUTS :
-
- None.
-
- ---------------------------------------
-
-
-
- rotate - Rotates an array of vectors using the current setxfm()
-
- vals without perspective.
-
-
-
- USAGE :
-
- rotate(v,n)
-
- VECTOR *v;
-
- int n;
-
-
-
- FUNCTION:
-
- This routine actually performs the translation of a group of
-
- points in 3-space based on the parameters set by setxfm().
-
-
-
- INPUTS :
-
- 'v' points to a vector structure which must be initialized with
-
- pointers to all 6 arrays of size >='n'. The first 'n' vectors
-
- will be rotated. Note that the 'x','y','z' VECTOR values are
-
-
-
-
-
- unchanged. These values are transformed, and the results are
-
- stored in 'tx','ty','tz'. If you wish to transform a subset of
-
- the points, a separate VECTOR structure pointing to the
-
- beginning of the subset can be used.
-
-
-
- OUTPUTS:
-
- none.
-
- ---------------------------------------
-
-
-
- rotatev - Rotates an array of vectors using the current setxfm
-
- vals with perspective.
-
-
-
- USAGE :
-
- rotatev(v,n)
-
- VECTOR *v;
-
- int n;
-
-
-
- FUNCTION:
-
- This routine actually performs the translation of a group of
-
- points in 3-space based on the parameters set by setxfm(). The
-
- only difference between this routine and rotate() is the
-
- addition of perspective.
-
-
-
- INPUTS :
-
- 'v' points to a vector structure which must be initialized with
-
- pointers to all 6 arrays of size >='n'. The first 'n' vectors
-
- will be rotated. Note that the 'x','y','z' VECTOR values are
-
- unchanged. These values are transformed, and the results are
- Page 8 - January 5, 1990
- stored in 'tx','ty','tz'. If you wish to transform a subset of
-
- the points, a separate VECTOR structure pointing to the
-
- beginning of the subset can be used.
-
-
-
- OUTPUTS:
-
- none.
-
- ---------------------------------------
-
-
-
- Init3Ras - Sets a rastport up for area fills.
-
-
-
- USAGE:
-
- Init3Ras(rp,rp2)
-
- struct RastPort *rp,*rp2;
-
-
-
- FUNCTION:
-
- This routine should be called once for each RastPort to be used
-
- with d3surf(). If it is called more than once with the same
-
- RastPort it could cause serious problems. This routine only
-
- needs to be called if d3surf() is going to be used. If only
-
- d3lines() is going to be used, you can save some memory by not
-
- calling this routine.
-
-
-
-
-
-
-
- INPUTS:
-
- 'rp' and 'rp2' point to RastPorts which will be used with
-
- d3surf(). d3surf uses area fill operations, so the RastPort it
-
- uses must be given temporary storage for use in the filling.
-
- 'rp2' should be set to NULL if only one RastPort is to be used.
-
- If both are passed, they will be assigned the same temporary
-
- storage area, thus saving a significant amount of memory.
-
-
-
- OUTPUTS:
-
- None.
-
- ---------------------------------------
-
-
-
- Exit3d - Frees up the memory allocated by Init3Ras.
-
-
-
- USAGE :
-
- Exit3d(rp)
-
- struct RastPort *rp;
-
-
-
- FUNCTION:
-
- This routine frees up the memory allocated by Init3Ras().
-
-
-
- INPUTS:
-
- 'rp' points to a RastPort initialized with Init3Ras(). If 2
-
- RastPorts were initialized with a SINGLE call to Init3Ras(),
-
- only ONE of the two should be passed to Exit3d(), and neither
-
- should be used with area fills again.
-
- I should explain this in more detail. If two RastPorts are
- Page 9 - January 5, 1990
- initialized with a single Init3Ras() call, both RastPorts will
-
- point to the same scratch memory area. Exit3d() frees this
-
- memory up. After you call it for one of the two RastPorts, the
-
- other one will point to an unallocated area in memory. If a fill
-
- operation is done at this time, it can cause all sorts of nasty
-
- problems. Be warned.
-
-
-
- OUTPUTS:
-
- None.
-
- ---------------------------------------
-
-
-
-
-
- d3lines - Draw a group of lines connecting points in 3 space.
-
-
-
- USAGE:
-
- d3lines(vector,line,n,rp)
-
- VECTOR *vector;
-
- LINES *line;
-
- int n;
-
- struct RastPort *rp;
-
-
-
- FUNCTION:
-
- This routine actually draws lines connecting one or more points
-
- in 3-space. See the information on the VECTOR and LINES
-
- structures for more info.
-
-
-
- INPUTS:
-
- 'vector' points to a VECTOR structure with information on the
-
- points to be used in the line drawing. 'line' points to an array
-
- of LINES structures which contains a description of how the
-
- lines are to be drawn. 'n' is the number of elements in the
-
- array pointed to by 'line'. 'rp' points to the RastPort where
-
- the lines should be drawn.
-
-
-
- OUTPUTS:
-
- none.
-
- ---------------------------------------
-
-
-
- d3surf - Draw a group of surfaces in 3 space.
-
-
- Page 10 - January 5, 1990
- USAGE:
-
- d3lines(vector,line,n,rp)
-
- VECTOR *vector;
-
- LINES *line;
-
- int n;
-
- struct RastPort *rp;
-
-
-
- FUNCTION:
-
- This routine is just like d3lines(), except filled polygons are
-
- drawn rather than lines. The polygons are sorted before drawing,
-
- so hidden line removal is accomplished.
-
-
-
- INPUTS:
-
- 'vector' points to a VECTOR structure with information on the
-
- points to be used in the surface drawing. 'line' points to an
-
- array of LINES structures which contains a description of how
-
- the surfaces are to be drawn. 'n' is the number of elements in
-
- the array pointed to by line. 'rp' points to the RastPort where
-
- the surfaces should be drawn.
-
-
-
- OUTPUTS: none.
-
-
-
-
-
- STRUCTURES :
-
-
-
- VECTOR ->
-
- long *x,*y,*z;
-
- long *tx,*ty,*tz;
-
-
-
- This structure points to the data for all the vertices that
-
- are transformed. 'x','y','z' are arrays with the untransformed
-
- vertex information. 'tx','ty','tz' are arrays which contain the
-
- transformed equivalents of the vertices. 'tx','ty','tz' are
-
- filled in by rotate() and rotatev(). They must be initialized to
-
- point to sufficiently large areas of free memory by the user.
-
- The 'x','y','z' values represent vertical pixels on the
-
- screen. ie - the point (10,1,10) without perspective would
-
- appear 10 pixels below and 22 pixels to the right of the defined
-
- center (using a 22/10) aspect ratio.
-
- -----------------------------------------
-
-
-
- LINES ->
-
- unsigned short l;
-
- unsigned short nl : 1,nc : 1, nco : 1;
-
-
-
- For those of you not familiar with the above notation, nl, nc,
-
- and nco are 1 bit integers allocated within a single unsigned
-
- short. An array of LINES structures contains the information for
-
- line/polygon drawing. The fact that 'l' is allocated as a short
-
- means that you can't have more than 2^16 vertices in any single
-
- array. Hopefully this won't present any problems.
- Page 11 - January 5, 1990
- The array of LINES should be used as follows :
-
- 'l' contains a vertex number in a VECTOR structure or a color
-
- (see below).
-
-
-
- 'nl' is set if this vertex is the beginning of a new
-
- line/polygon.
-
-
-
- 'nc' is set if 'l' represents a new fill color for polygons.
-
-
-
- 'nco' is set if 'l' represents a new outline color for polygons,
-
- or a new line color for line drawing.
-
-
-
- If filled shapes are to be drawn, not just lines, be sure that
-
- each new line represents a new polygon. That is, don't draw two
-
- filled shapes with one continuous line. This would look fine for
-
- d3lines(), but would produce strange effects with d3surf().
-
- Points in filled shapes need not be in the same plane, but think
-
- carefully before trying this. Some shapes may look strange in
-
- some perspectives.
-
- Color changes with d3lines() may occur anywhere. However,
-
- color changes used with d3surf() must occur only immediately
-
-
-
-
-
- after a nl=1 element. This is due to the way hidden line removal
-
- works. Every nl=1 element is taken to be the beginning of a new
-
- polygon. These polygons are then sorted so the farthest ones are
-
- drawn first. Color changes occurring before a nl=1 point will be
-
- attached to the wrong polygon when they are sorted. Color
-
- changes in the middle of the shape may not have the desired
-
- effect (after 1 or more lines have been added).
-
-
-
- Here is a sample LINES array to make this all more clear :
-
-
-
- l nl nc nco
-
- 0 0 1 0 0 <- Starts a shape, vertex 0
-
- 1 2 0 0 1 <- Changes to outline color 2
-
- 2 1 0 1 0 <- Changes to filled color 1
-
- 3 1 0 0 0
-
- 4 2 0 0 0
-
- 5 3 0 0 0
-
- 6 0 0 0 0 <- Closes the quad., not necessary
-
- for d3surf().
-
- 7 3 0 0 1 <- Changes outline color. This is
-
- fine for d3lines(), but won't
-
- change correctly for d3surf().
-
- 8 4 1 0 0 <- New shape
-
- 9 5 0 0 0
-
- 10 6 0 0 0 <- No color was defined after the
-
- new shape started, so the color
-
- from the last drawn shape will
-
- be used. The shape is not
- Page 12 - January 5, 1990
- closed. d3surf() will close the
-
- shape anyway. d3lines won't.
-
-
-
- In the above example, 0-6 will draw a quadrilateral in color 2
-
- if d3lines() is used. It will draw a filled quad., filled with
-
- color 1 and outlined in color 2, if d3surf() is used.
-
-
-
-
-
- ROTATIONS, AND HOW THEY'RE DONE
-
- -------------------------------
-
- This program uses a very standard scheme for rotating objects
-
- which is completely general. That is, you can observe your
-
- 'scene' from absolutely any imaginable perspective (within the
-
- bounds of integer math).
-
- The axes are set up as follows :
-
-
-
- Z| / Y
-
- | /
-
- | /
-
- |/
-
- -------------
-
- X
-
-
-
- That is, the X axis is the screen x axis, the Z axis is the
-
- screen y axis, and the Y axis goes positive into the screen.
-
-
-
- Rotations are defined in terms of three steps. 'a1' defines a
-
- rotation angle from the X axis in the X-Y plane. 'a2' then
-
- rotates the specified number of radians away from the Z axis in
-
- the Y-Z plane. Finally 'a3' defines a rotation in radians from
-
- the new (rotated) X axis in the new X-Y plane.
-
- Explained another way : Say the ground is in the X-Y plane, ie
-
- going into the screen. 'a1' would spin an object resting on the
-
- ground as if it were a top. 'a2' would cause this rotated object
-
- to tilt on the screen, just like the Aster*ids spaceship spins.
-
- 'a3' would take the tilted object and spin it along the tilted
- Page 13 - January 5, 1990
- plane. a3 is a bit hard to picture, play with it.
-
- I know this is somewhat complex, but you can do any possible
-
- rotation with it once you get the hang of it. It may also be
-
- easier to visualize if you picture the observer moving, rather
-
- than the object being rotated. I may try to add a few other
-
- schemes in the next version. We'll see what I can find.
-
- For those of you who are interested you can see how this
-
- transformation works in "Classical Mechanics" by Goldstein on
-
- page 146. (What can I say, I'm a physics major.)
-
-
-
- ---------
-
-
-
- Again, if you run into any bugs or problems please let me
-
- know. Also keep in mind that, while you may feel free to modify
-
- this code, you might have compatibility problems if you do. I
-
- tried to comment the code as well as possible for those of you
-
- who feel like making changes. Have fun !!!
-